import { Injectable, Logger, BadRequestException, InternalServerErrorException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CopilotConfig } from '../../database/entities/copilot-config.entity';
import { 
  CopilotConfigDto, 
  UpdateCopilotConfigDto, 
  TestConnectionDto, 
  TestConnectionResponseDto,
  ProxyConfigResponseDto
} from '../dto/config.dto';
import { ProxyConfigService, ProxyMode } from '../config/proxy.config';
import { ForwardingService } from './forwarding.service';
import { TokenManagerService } from './token-manager.service';

@Injectable()
export class ConfigManagementService {
  private readonly logger = new Logger(ConfigManagementService.name);

  constructor(
    private readonly proxyConfigService: ProxyConfigService,
    private readonly forwardingService: ForwardingService,
    private readonly tokenManager: TokenManagerService,
    @InjectRepository(CopilotConfig)
    private readonly copilotConfigRepository: Repository<CopilotConfig>
  ) {
    // 初始化默认配置
    this.initializeDefaultConfig();
  }

  /**
   * 获取当前配置
   */
  async getProxyConfig(): Promise<ProxyConfigResponseDto> {
    const mode = this.proxyConfigService.getProxyMode();
    const copilotConfig = await this.proxyConfigService.getCopilotConfig();
    
    const tokenInfo = this.parseTokenInfo(copilotConfig.authToken);
    
    return {
      mode: mode,
      debug: await this.proxyConfigService.isDebugMode(),
      timeout: await this.proxyConfigService.getRequestTimeout(),
      maxRetries: await this.proxyConfigService.getMaxRetries(),
      logRequests: await this.proxyConfigService.shouldLogRequests(),
      logResponses: await this.proxyConfigService.shouldLogResponses(),
      copilot: {
        apiUrl: copilotConfig.apiUrl,
        defaultModel: copilotConfig.defaultModel,
        hasGithubToken: !!copilotConfig.githubToken && copilotConfig.githubToken.length > 10,
        hasAuthToken: !!copilotConfig.authToken && copilotConfig.authToken.length > 10,
        tokenValid: tokenInfo?.valid || false,
        tokenExpiry: tokenInfo?.expiresAt,
        userAgent: copilotConfig.userAgent,
        proxy: {
          enabled: copilotConfig.proxy?.enabled || false,
          url: copilotConfig.proxy?.url || '',
          hasAuth: !!(copilotConfig.proxy?.username && copilotConfig.proxy?.password)
        }
      }
    };
  }

  /**
   * 初始化默认配置
   */
  private async initializeDefaultConfig(): Promise<void> {
    try {
      const existingConfig = await this.copilotConfigRepository.findOne({
        where: { configName: 'default', isActive: true }
      });
      
      if (!existingConfig) {
        const defaultConfig = this.copilotConfigRepository.create({
          configName: 'default',
          isActive: true
        });
        await this.copilotConfigRepository.save(defaultConfig);
        this.logger.log('Default Copilot configuration created');
      }
    } catch (error) {
      this.logger.warn(`Failed to initialize default config: ${error.message}`);
    }
  }

  /**
   * 获取数据库配置
   */
  private async getDatabaseConfig(): Promise<CopilotConfig> {
    let config = await this.copilotConfigRepository.findOne({
      where: { configName: 'default', isActive: true }
    });
    
    if (!config) {
      config = this.copilotConfigRepository.create({
        configName: 'default',
        isActive: true
      });
      config = await this.copilotConfigRepository.save(config);
    }
    
    return config;
  }

  /**
   * 更新 Copilot 配置
   */
  async updateCopilotConfig(updateDto: UpdateCopilotConfigDto): Promise<{ success: boolean; message: string }> {
    try {
      // 获取当前配置
      const config = await this.getDatabaseConfig();
      
      // 更新配置项
      if (updateDto.githubToken !== undefined) {
        // 验证 GitHub token 格式
        if (updateDto.githubToken && !this.validateGithubTokenFormat(updateDto.githubToken)) {
          throw new BadRequestException('Invalid GitHub token format. Expected format: ghu_...');
        }
        config.githubToken = updateDto.githubToken;
      }
      
      if (updateDto.authToken !== undefined) {
        // 验证 Copilot token 格式
        if (updateDto.authToken && !this.validateCopilotTokenFormat(updateDto.authToken)) {
          throw new BadRequestException('Invalid Copilot token format. Expected format: tid=...;exp=...;...');
        }
        config.authToken = updateDto.authToken;
      }
      
      if (updateDto.apiUrl !== undefined) {
        // 验证 API URL 格式
        if (updateDto.apiUrl && !this.isValidUrl(updateDto.apiUrl)) {
          throw new BadRequestException('Invalid API URL format. Expected format: https://api.example.com');
        }
        config.apiUrl = updateDto.apiUrl;
      }
      
      if (updateDto.defaultModel !== undefined) {
        config.defaultModel = updateDto.defaultModel;
      }
      
      if (updateDto.timeout !== undefined) {
        config.timeout = updateDto.timeout;
      }
      
      if (updateDto.retryAttempts !== undefined) {
        config.retryAttempts = updateDto.retryAttempts;
      }

      // 处理代理配置
      if (updateDto.proxy !== undefined) {
        if (updateDto.proxy.enabled !== undefined) {
          config.proxyEnabled = updateDto.proxy.enabled;
        }
        if (updateDto.proxy.url !== undefined) {
          if (updateDto.proxy.url && !this.validateProxyUrl(updateDto.proxy.url)) {
            throw new BadRequestException('Invalid proxy URL format');
          }
          config.proxyUrl = updateDto.proxy.url;
        }
        if (updateDto.proxy.username !== undefined) {
          config.proxyUsername = updateDto.proxy.username;
        }
        if (updateDto.proxy.password !== undefined) {
          config.proxyPassword = updateDto.proxy.password;
        }
      }

      // 保存到数据库
      await this.copilotConfigRepository.save(config);
      
      this.logger.log('Copilot configuration updated successfully');
      
      return {
        success: true,
        message: 'Configuration updated successfully.'
      };
    } catch (error) {
      this.logger.error(`Failed to update Copilot config: ${error.message}`, error.stack);
      throw new InternalServerErrorException(`Failed to update configuration: ${error.message}`);
    }
  }

  /**
   * 测试 Token 连接
   */
  async testConnection(testDto?: TestConnectionDto): Promise<TestConnectionResponseDto> {
    const startTime = Date.now();
    
    // 使用保存的token而不是页面输入的token
    const copilotConfig = await this.proxyConfigService.getCopilotConfig();
    const authToken = copilotConfig.authToken;
    
    try {
      
      if (!authToken) {
        return {
          success: false,
          message: 'No saved Copilot token found',
          error: 'Please save a Copilot token first',
          responseTime: Date.now() - startTime
        };
      }
      
      // 验证 token 格式
      if (!this.validateCopilotTokenFormat(authToken)) {
        return {
          success: false,
          message: 'Invalid Copilot token format',
          error: 'Saved token should be in format: tid=...;exp=...;...',
          responseTime: Date.now() - startTime
        };
      }

      // 解析 token 信息
      const tokenInfo = this.parseTokenInfo(authToken);
      
      // 检查 token 是否过期
      if (tokenInfo && !tokenInfo.valid) {
        return {
          success: false,
          message: 'Token has expired',
          error: `Token expired at ${tokenInfo.expiresAt}`,
          responseTime: Date.now() - startTime,
          tokenInfo
        };
      }

      // 临时更新环境变量进行测试
      const originalToken = process.env.COPILOT_AUTH_TOKEN;
      const originalMode = process.env.ANTHROPIC_PROXY_MODE;
      
      process.env.COPILOT_AUTH_TOKEN = authToken;
      process.env.ANTHROPIC_PROXY_MODE = 'copilot';

      try {
        // 创建测试消息
        const testMessage = testDto?.testMessage || 'Hello, this is a connection test.';
        
        const testRequest = {
          model: 'claude-3.5-sonnet',
          max_tokens: 50,
          messages: [
            {
              role: 'user' as const,
              content: testMessage
            }
          ]
        };

        // 发送测试请求
        const response = await this.forwardingService.forwardMessageRequest(testRequest, {
          ip: '127.0.0.1',
          userAgent: 'Anthropic-Proxy-Test',
          headers: {}
        });

        const responseTime = Date.now() - startTime;

        this.logger.log(`Connection test successful, response time: ${responseTime}ms`);

        return {
          success: true,
          message: 'Connection test successful',
          responseTime,
          tokenInfo
        };

      } finally {
        // 恢复原始环境变量
        if (originalToken) {
          process.env.COPILOT_AUTH_TOKEN = originalToken;
        } else {
          delete process.env.COPILOT_AUTH_TOKEN;
        }
        
        if (originalMode) {
          process.env.ANTHROPIC_PROXY_MODE = originalMode;
        } else {
          delete process.env.ANTHROPIC_PROXY_MODE;
        }
      }

    } catch (error) {
      const responseTime = Date.now() - startTime;
      
      this.logger.warn(`Connection test failed: ${error.message}`);
      
      return {
        success: false,
        message: 'Connection test failed',
        error: error.message,
        responseTime,
        tokenInfo: this.parseTokenInfo(authToken)
      };
    }
  }


  /**
   * 切换代理模式
   */
  async switchMode(mode: 'mock' | 'copilot'): Promise<{ success: boolean; message: string; currentMode: string }> {
    try {
      const currentMode = this.proxyConfigService.getProxyMode();
      
      if (mode === currentMode) {
        return {
          success: true,
          message: `Already in ${mode} mode`,
          currentMode: mode
        };
      }

      // 如果切换到 copilot 模式，检查是否有有效 token
      if (mode === 'copilot') {
        const config = await this.getDatabaseConfig();
        if (!config.authToken || !this.validateCopilotTokenFormat(config.authToken)) {
          throw new BadRequestException('Valid Copilot auth token is required for copilot mode');
        }
      }

      // 更新代理配置服务的模式
      this.proxyConfigService.setProxyMode(mode as any);
      
      this.logger.log(`Proxy mode switched from ${currentMode} to ${mode}`);
      
      return {
        success: true,
        message: `Mode switched to ${mode} successfully`,
        currentMode: mode
      };
    } catch (error) {
      this.logger.error(`Failed to switch mode: ${error.message}`, error.stack);
      throw new InternalServerErrorException(`Failed to switch mode: ${error.message}`);
    }
  }

  /**
   * 获取 Token 信息
   */
  async getTokenInfo(): Promise<any> {
    const copilotConfig = await this.proxyConfigService.getCopilotConfig();
    return this.parseTokenInfo(copilotConfig.authToken);
  }

  /**
   * 验证 GitHub Token 格式
   */
  private validateGithubTokenFormat(token: string): boolean {
    if (!token || typeof token !== 'string') {
      return false;
    }
    
    // GitHub token 格式检查 (ghu_ 开头)
    return token.startsWith('ghu_') && token.length > 10;
  }

  /**
   * 验证 Copilot Token 格式
   */
  private validateCopilotTokenFormat(token: string): boolean {
    if (!token || typeof token !== 'string') {
      return false;
    }
    
    // 检查是否包含必要的字段
    const requiredFields = ['tid=', 'exp='];
    return requiredFields.every(field => token.includes(field));
  }

  /**
   * 解析 Token 信息
   */
  private parseTokenInfo(token: string): { valid: boolean; expiresAt?: string; sku?: string; userId?: string } | null {
    if (!token || !this.validateCopilotTokenFormat(token)) {
      return null;
    }

    try {
      const params = new URLSearchParams(token.replace(/;/g, '&'));
      
      const tidValue = params.get('tid');
      const expValue = params.get('exp');
      const skuValue = params.get('sku');
      
      if (!expValue) {
        return { valid: false };
      }

      const expiryTimestamp = parseInt(expValue) * 1000;
      const expiryDate = new Date(expiryTimestamp);
      const isValid = expiryTimestamp > Date.now();
      
      return {
        valid: isValid,
        expiresAt: expiryDate.toISOString(),
        sku: skuValue || undefined,
        userId: tidValue || undefined
      };
    } catch (error) {
      this.logger.warn(`Failed to parse token info: ${error.message}`);
      return { valid: false };
    }
  }


  /**
   * 手动刷新 Copilot Token
   */
  async refreshToken(): Promise<{ success: boolean; message: string; tokenInfo?: any }> {
    try {
      this.logger.log('Manual token refresh requested');
      
      // 清除当前缓存的token，强制刷新
      this.tokenManager.clearToken();
      
      // 获取新的有效token
      const newToken = await this.tokenManager.getValidToken();
      
      // 获取token信息
      const tokenInfo = this.tokenManager.getTokenInfo();
      
      this.logger.log('New token obtained from TokenManager', {
        tokenLength: newToken.length,
        tokenPrefix: newToken.substring(0, 50) + '...',
        expiresAt: tokenInfo.expiresAt,
        isValid: tokenInfo.isValid
      });
      
      // 更新数据库配置
      const config = await this.getDatabaseConfig();
      config.authToken = newToken;
      await this.copilotConfigRepository.save(config);
      
      this.logger.log('Token refreshed and saved to configuration', {
        expiresAt: tokenInfo.expiresAt,
        isValid: tokenInfo.isValid,
        configUpdated: true
      });
      
      return {
        success: true,
        message: 'Token refreshed successfully and saved to configuration',
        tokenInfo: {
          valid: tokenInfo.isValid,
          expiresAt: new Date(tokenInfo.expiresAt * 1000).toISOString(),
          token: newToken.substring(0, 50) + '...' // 只显示部分token
        }
      };
    } catch (error) {
      this.logger.error(`Failed to refresh token: ${error.message}`, error.stack);
      return {
        success: false,
        message: `Token refresh failed: ${error.message}`
      };
    }
  }

  /**
   * 获取 Token 健康状态
   */
  async getTokenHealth(): Promise<any> {
    try {
      // 获取token管理器状态
      const tokenHealth = await this.tokenManager.checkHealth();
      
      // 获取ForwardingService的健康状态
      const forwardingHealth = await this.forwardingService.checkForwardingHealth();
      
      const tokenInfo = this.tokenManager.getTokenInfo();
      
      let expiresIn = 0;
      let status = 'unknown';
      
      if (tokenInfo.isValid && tokenInfo.expiresAt > 0) {
        const now = Math.floor(Date.now() / 1000);
        expiresIn = Math.max(0, tokenInfo.expiresAt - now);
        
        if (expiresIn > 3600) {
          status = 'healthy';
        } else if (expiresIn > 300) {
          status = 'warning';
        } else {
          status = 'critical';
        }
      } else {
        status = 'invalid';
      }
      
      return {
        status,
        tokenManager: tokenHealth,
        forwarding: forwardingHealth,
        token: {
          valid: tokenInfo.isValid,
          expiresAt: tokenInfo.expiresAt > 0 ? new Date(tokenInfo.expiresAt * 1000).toISOString() : null,
          expiresIn: expiresIn,
          expiresInMinutes: Math.floor(expiresIn / 60),
          status: status
        },
        lastCheck: new Date().toISOString()
      };
    } catch (error) {
      this.logger.error(`Failed to get token health: ${error.message}`, error.stack);
      return {
        status: 'error',
        message: error.message,
        lastCheck: new Date().toISOString()
      };
    }
  }

  /**
   * 验证代理 URL 格式
   */
  private validateProxyUrl(url: string): boolean {
    if (!url || typeof url !== 'string') {
      return false;
    }
    
    try {
      const urlObj = new URL(url);
      return ['http:', 'https:', 'socks4:', 'socks5:'].includes(urlObj.protocol);
    } catch (error) {
      return false;
    }
  }

  /**
   * 验证 API URL 格式
   */
  private isValidUrl(url: string): boolean {
    if (!url || typeof url !== 'string') {
      return false;
    }
    
    try {
      const urlObj = new URL(url);
      return ['http:', 'https:'].includes(urlObj.protocol);
    } catch (error) {
      return false;
    }
  }

}